home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / tracker-4.13.lha / tracker / Amiga / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-14  |  11.2 KB  |  446 lines

  1. /* amiga/main.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* plays sound/noisetracker files on Sparc, silicon graphics.
  6.  * Authors  : Liam Corner - zenith@dcs.warwick.ac.uk
  7.  *            Marc Espie - espie@ens.fr
  8.  *            Steve Haehnichen - shaehnic@ucsd.edu
  9.  *            Andrew Leahy - alf@st.nepean.uws.edu.au
  10.  *
  11.  * Usage    : tracker <filename> 
  12.  *  this version plays compressed files as well.
  13.  *    Modified version of the standard main.c
  14.  */
  15.  
  16. /* $Id: main.c,v 1.12 1995/02/14 16:51:22 espie Exp espie $
  17.  * $Log: main.c,v $
  18.  * Revision 1.12  1995/02/14  16:51:22  espie
  19.  * *** empty log message ***
  20.  *
  21.  * Revision 1.11  1995/02/13  22:05:42  espie
  22.  * Added new speedmode option.
  23.  *
  24.  * Revision 1.10  1995/01/13  13:31:35  espie
  25.  * *** empty log message ***
  26.  *
  27.  * Revision 1.12  1994/06/22  00:24:51  Espie
  28.  * Added wb2cli, workbench support !
  29.  * File requester !
  30.  * Uncentralized event handling using event management functions.
  31.  * Suppressed calls to run_in_fg().
  32.  * Added check for / in song names to display something sensible
  33.  * in the title bar...
  34.  * Corrected minor previous song bug.
  35.  * Suppressed spurious code.
  36.  * Added CUT/ADD keywords.
  37.  * Branching to amiga version from unix version 3.20
  38.  */
  39.      
  40.  
  41. #include <exec/types.h>
  42. #include <exec/memory.h>
  43. #include <proto/dos.h>
  44. #include <proto/exec.h>
  45. #include <dos/dosasl.h>
  46. #include <dos/dosextens.h>
  47. #include <exec/libraries.h>
  48.      
  49. #include "defs.h"
  50. #include "version.h"
  51.  
  52. #include <signal.h>
  53.  
  54. #include "song.h"
  55. #include "extern.h"
  56.  
  57. #include "tags.h"
  58. #include "prefs.h"
  59. #include "amiga/amiga.h"
  60. #include "amiga/wb2cli.h"
  61.      
  62. ID("$Id: main.c,v 1.12 1995/02/14 16:51:22 espie Exp espie $")
  63.  
  64.  
  65. LOCAL char *amiga_version = "$VER: tracker "VERSION"$";
  66.  
  67. LOCAL struct MinList temp;
  68.  
  69. LOCAL void print_usage()
  70.    {
  71.    GENERIC handle;
  72.    
  73.    handle = begin_info("Usage");
  74.    info(handle, "Usage: tracker files OPTIONS");
  75.    info(handle, "HELP               Display usage information");
  76.    info(handle, "QUIET              Print no output other than errors");
  77.    info(handle, "PICKY              Do not tolerate any faults (default is to ignore most)");
  78.    info(handle, "TOLERANT           Ignore all faults");
  79.    info(handle, "VERBOSE            Show text representation of song");
  80.    info(handle, "REPEATS count      Number of repeats (0 is forever) (default 1)");
  81.    info(handle, "SPEED speed        Song speed.  Some songs want 60 (default 50)");
  82.    info(handle, "SPEEDMODE old | normal | finefirst | normalfirst");
  83.    info(handle, "NEW/OLD/BOTH       Select default reading type (default is BOTH)");
  84.    info(handle, "TRANSPOSE n        Transpose notes up by n halftones");
  85.    info(handle, "SCROLL             Show notes scrolling by");
  86.    info(handle, "CUT ab1            Play all instruments except number 1 a and b");
  87.    info(handle, "ADD ab1            Play only instruments except number 1 a and b");
  88.    info(handle, "GUI                open GUI directly");
  89.    end_info(handle);
  90.    }
  91.  
  92. /* arg parser for command-line options. */
  93.  
  94. LOCAL char *template = 
  95. "FILES/M,HELP/S,QUIET/S,TOLERANT/S,PICKY/S,NEW/S,OLD/S,BOTH/S,V=VERBOSE/S,\
  96. TRANS=TRANSPOSE/K/N,R=REPEATS/K,SPEED/K/N,START/K,\
  97. CUT/K,ADD/K,SCROLL/S,GUI/S,SPEEDMODE/K";
  98.  
  99. #define OPT_HELP 1
  100. #define OPT_QUIET 2
  101. #define OPT_TOLERANT 3
  102. #define OPT_PICKY 4
  103. #define OPT_NEW 5
  104. #define OPT_OLD 6
  105. #define OPT_BOTH 7
  106. #define OPT_VERBOSE 8
  107. #define OPT_TRANSPOSE 9
  108. #define OPT_REPEATS 10
  109. #define OPT_SPEED 11
  110. #define OPT_START 12
  111. #define OPT_CUT 13
  112. #define OPT_ADD 14
  113. #define OPT_SHOW 15
  114. #define OPT_GUI 16
  115. #define OPT_SPEEDMODE 17
  116.  
  117. LOCAL LONG args[19];
  118.  
  119. LOCAL struct RDArgs *rdargs = 0;
  120.  
  121. LOCAL void free_args()
  122.    {
  123.    if (rdargs)
  124.       FreeArgs(rdargs);
  125.    }
  126.  
  127. /* global variable to catch various types of errors
  128.  * and achieve the desired flow of control
  129.  */
  130. int error;
  131.  
  132. LOCAL struct song *do_read_song(name, type)
  133. char *name;
  134. int type;
  135.    {
  136.    struct song *song;
  137.    struct exfile *file;
  138.  
  139.    file = open_file(name, "r", getenv("MODPATH"));
  140.    if (!file)
  141.       return NULL;
  142.    song = read_song(file, type); 
  143.    close_file(file);
  144.    return song;
  145.    }
  146.  
  147. LOCAL int start;
  148. LOCAL int transpose;
  149.  
  150.  
  151. LOCAL void use_options()
  152.    {
  153.    char *s;
  154.    
  155.    if ((s = args[OPT_CUT]) || (s = args[OPT_ADD]))
  156.       {
  157.       char c;
  158.       ULONG imask = 0;
  159.       
  160.       while (c = *s++)
  161.          {
  162.          if (c >= '1' && c <= '9')
  163.             imask |= 1<< (c-'1');
  164.          else if (c >= 'A' && c <= 'Z')
  165.             imask |= 1 << (c-'A'+9);
  166.          else if (c >= 'a' && c <= 'z')
  167.             imask |= 1 << (c-'a'+9);
  168.          }
  169.       if (args[OPT_CUT])
  170.          set_pref_scalar(PREF_IMASK, imask);
  171.       else
  172.          set_pref_scalar(PREF_IMASK, ~imask);
  173.       }        
  174.    if (args[OPT_OLD])
  175.       set_pref_scalar(PREF_TYPE, OLD);
  176.    if (args[OPT_NEW])
  177.       set_pref_scalar(PREF_TYPE, NEW);
  178.    if (args[OPT_SPEEDMODE])
  179.       {
  180.         if (stricmp(args[OPT_SPEEDMODE], "old") == 0)
  181.             set_pref_scalar(PREF_SPEEDMODE, OLD_SPEEDMODE);
  182.         else if (stricmp(args[OPT_SPEEDMODE], "normal") == 0)
  183.             set_pref_scalar(PREF_SPEEDMODE, NORMAL_SPEEDMODE);
  184.         else if (stricmp(args[OPT_SPEEDMODE], "finefirst") == 0)
  185.             set_pref_scalar(PREF_SPEEDMODE, FINESPEED_ONLY);
  186.         else if (stricmp(args[OPT_SPEEDMODE], "normalfirst") == 0)
  187.             set_pref_scalar(PREF_SPEEDMODE, SPEED_ONLY);
  188.        }
  189.    if (args[OPT_SHOW])
  190.       set_pref_scalar(PREF_SHOW, TRUE);
  191.    if (args[OPT_BOTH])
  192.       set_pref_scalar(PREF_TYPE, BOTH);
  193.    if (args[OPT_REPEATS])
  194.       set_pref_scalar(PREF_REPEATS, *((ULONG *)args[OPT_REPEATS]));
  195.    if (args[OPT_SPEED])
  196.       set_pref_scalar(PREF_SPEED, *((ULONG *)args[OPT_SPEED]));
  197.    if (args[OPT_TRANSPOSE])
  198.       transpose = *((LONG *)args[OPT_TRANSPOSE]);
  199.    if (args[OPT_PICKY])
  200.       set_pref_scalar(PREF_TOLERATE, 0);
  201.    else if (args[OPT_TOLERANT])
  202.       set_pref_scalar(PREF_TOLERATE, 0);
  203.    if (args[OPT_START])
  204.       start = *((ULONG *)args[OPT_START]);
  205.    if (args[OPT_HELP])
  206.       {
  207.       print_usage();
  208.       end_all(0);
  209.       }
  210.    if (args[OPT_VERBOSE])
  211.       set_pref_scalar(PREF_DUMP, TRUE);
  212.    }
  213.  
  214. LOCAL struct song *load_song(name)
  215. char *name;
  216.    {
  217.    struct song *song;
  218.    char *buffer;
  219.    int i, j;
  220.    
  221.    i = strlen(name);
  222.    
  223.    for (j = i; j > 0; j--)
  224.       if (name[j] == '/' || name[j] == ':')
  225.          {
  226.          j++;
  227.          break;
  228.          }
  229.    
  230.    buffer = malloc( i - j + 5);
  231.    if (buffer)
  232.       {
  233.       sprintf(buffer, "%s...", name + j);
  234.       status(buffer);
  235.       }
  236.  
  237.    switch(get_pref_scalar(PREF_TYPE))
  238.       {
  239.    case BOTH:
  240.       song = do_read_song(name, NEW);
  241.       if (song)
  242.          break;
  243.       /* FALLTHRU */
  244.    case OLD:
  245.       song = do_read_song(name, OLD);
  246.       break;
  247.       /* this is explicitly flagged as a new module,
  248.        * so we don't need to look for a signature.
  249.        */
  250.    case NEW:
  251.       song = do_read_song(name, NEW_NO_CHECK);
  252.       break;
  253.       }
  254.    if (buffer)
  255.       {
  256.       status(0);
  257.       free(buffer);
  258.       }
  259.    return song;
  260.    }
  261.  
  262.  
  263. #define PATHSIZE 250
  264.  
  265. struct MinList *expand_names(char *pat[])
  266.    {
  267.    int i;
  268.    struct AnchorPath *ap;
  269.    int error;
  270.    int total;
  271.    struct amiganame *new;
  272.    
  273.    NewList(&temp);
  274.    ap = AllocVec(sizeof(struct AnchorPath) + PATHSIZE, MEMF_CLEAR);
  275.    if (!ap)
  276.       end_all(0);
  277.    ap->ap_Strlen = PATHSIZE;
  278.    for (i = 0; pat && pat[i]; i++)
  279.       {
  280.       for (error = MatchFirst(pat[i], ap); !error; error = MatchNext(ap))
  281.          {
  282.          total = strlen(ap->ap_Buf) +1 ;
  283.          if (strcmp(ap->ap_Buf + total -6, ".info") == 0)
  284.             continue;
  285.          new = malloc(sizeof(struct amiganame) + total);
  286.          if (!new)
  287.             continue;
  288.          strcpy(new->s, ap->ap_Buf);
  289.          new->i = TRUE;
  290.             AddTail(&temp, new);
  291.          }
  292.       MatchEnd(ap);
  293.       }
  294.    FreeVec(ap);
  295.    return &temp;
  296.    }
  297.       
  298. /* add test for >=37 */
  299.  
  300. XT struct DosLibrary *DOSBase;      
  301. XT struct WBStartup *_WBenchMsg;
  302.  
  303. int main(argc, argv)
  304. int argc;
  305. char **argv;
  306.    {
  307.    struct song *song;
  308.    struct MinList *list;
  309.    struct amiganame *element, *i;
  310.  
  311.    struct tag *result;
  312.  
  313.    if (DOSBase->dl_lib.lib_Version < 37)
  314.       end_all("Need OS >= 2.04");
  315.  
  316.    start = 0;
  317.    set_pref_scalar(PREF_IMASK, 0);
  318.    set_pref_scalar(PREF_BCDVOL, 0);
  319.    set_pref_scalar(PREF_DUMP, FALSE);
  320.    set_pref_scalar(PREF_SHOW, FALSE);
  321.    set_pref_scalar(PREF_SYNC, FALSE);
  322.    set_pref_scalar(PREF_TYPE, BOTH);
  323.    set_pref_scalar(PREF_REPEATS, 1);
  324.    set_pref_scalar(PREF_SPEED, 50);
  325.    set_pref_scalar(PREF_TOLERATE, 1);
  326.  
  327.    if (argc == 1)
  328.       {
  329.       print_usage();
  330.       end_all(0);
  331.       }
  332.  
  333.    transpose = read_env("TRANSPOSE", 0);
  334.  
  335.  
  336.    if (argc > 0)     /* CLI */
  337.       {
  338.       /* check the command name for default reading type */
  339.  
  340.       rdargs = ReadArgs(template, args, 0);
  341.       if (rdargs)
  342.          at_end(free_args);
  343.       else
  344.          end_all(0);
  345.    
  346.       use_options();
  347.    
  348.       list = expand_names(args[0]);
  349.       }
  350.    else
  351.       (void)WB2CLI(_WBenchMsg, 4000, DOSBase);
  352.  
  353. again:      
  354.    if (argc == 0 || args[OPT_GUI])
  355.       {
  356.          /* force the interface to appear BEFORE the requester */
  357.       status(0);
  358.       launch_requester();
  359.       list = 0;
  360.       forever
  361.          {
  362.          result = get_ui();
  363.          while (result = get_tag(result))
  364.             {
  365.                /* forgotten from previous versions ! */
  366.             if (result->type == UI_QUIT)
  367.                end_all(0);
  368.             if (result->type == UI_LOAD_SONG)
  369.                {
  370.                i = (struct amiganame *)result->data.pointer;
  371.                if (!i)
  372.                   end_all(0);
  373.                temp.mlh_Tail = 0;
  374.                temp.mlh_Head = i;
  375.                temp.mlh_TailPred = i->n.mln_Pred;
  376.                i->n.mln_Pred->mln_Succ = &(temp.mlh_Tail);
  377.                i->n.mln_Pred = &temp;
  378.                list = &temp;
  379.                break;
  380.                }
  381.             }
  382.          if (list)
  383.             break;
  384.          await_events();
  385.          }
  386.       }
  387.       
  388.    for (element = list->mlh_Head; element->n.mln_Succ; element = element->n.mln_Succ)
  389.       {
  390.       if (!element->i)
  391.          continue;
  392.       song = load_song(element->s);   
  393.       if (song)
  394.          element->i = TRUE;
  395.       else
  396.          {
  397.          char buffer[150];
  398.  
  399.          sprintf(buffer, "%s is not a song", element->s);
  400.          notice(buffer);
  401.          element->i = FALSE;
  402.          continue;
  403.          }
  404. play_on:
  405.       if (get_pref_scalar(PREF_DUMP))
  406.          dump_song(song); 
  407.       transpose_song(song, transpose);
  408.       setup_audio(0, 1, 1);   /* doesn't really matter on the amiga */
  409.       set_busy_pointer(FALSE);
  410.       result = play_song(song, start);
  411.       set_busy_pointer(TRUE);
  412.       release_song(song);
  413.       while (result = get_tag(result))
  414.          {
  415.          switch (result->type)
  416.             {
  417.          case PLAY_PREVIOUS_SONG:
  418.             for (element = element->n.mln_Pred; element->n.mln_Pred; 
  419.                element = element->n.mln_Pred)
  420.                if (element->i)
  421.                   {
  422.                   song = load_song(element->s);
  423.                   goto play_on;
  424.                   }
  425.             break;
  426.          case PLAY_LOAD_SONG:
  427.                /* splice play load song result into list */
  428.             i = (struct amiganame *)result->data.pointer;
  429.             element->n.mln_Succ->mln_Pred = i->n.mln_Pred;
  430.             i->n.mln_Pred->mln_Succ = element->n.mln_Succ;
  431.             element->n.mln_Succ = i;
  432.             i->n.mln_Pred = element;
  433.          default:
  434.             break;
  435.             }
  436.          result++;
  437.          }
  438.             
  439.       }
  440.    if (argc == 0 || args[OPT_GUI])
  441.       goto again;
  442.    end_all(0);
  443.    /* NOTREACHED */
  444.    }
  445.  
  446.